<?php
declare (strict_types=1);

namespace app\datacenter\service;

use app\BaseService;
use app\datacenter\model\Areas;
use app\datacenter\model\LargeScreenCostStatistics;
use app\datacenter\model\Machine;
use app\datacenter\model\Member;
use app\datacenter\model\MemberCost;
use app\datacenter\model\Shop;
use app\datacenter\model\Users;
use emqx\EmqxHttpApi;
use redis\RedisTools;

/**
 * 大屏服务层
 */
class LargeScreenService extends BaseService
{

    /**
     * 获取大屏各个模块数据
     * @param int $type 模块类型
     * @return mixed
     */
    public function getData(int $type): mixed
    {
        if ($type == 1) {
            $data = $this->equipment();
        } elseif ($type == 2) {
            $data = $this->merchDayLive();
        } elseif ($type == 3) {
            $data = $this->outBagNumDay();
        } elseif ($type == 4) {
            $data = $this->outBagTodayRank();
        } elseif ($type == 5) {
            $data = $this->outBagMapsData();
        } else {
            $data = [];
        }
        $EmqxHttpApi = new EmqxHttpApi();
        return $EmqxHttpApi->publish($EmqxHttpApi->emqx_datacenter_topic_js, ['type' => $type, 'data' => $data]);
    }


    /**
     * 获取设备在线模块数据
     * @return int[]
     */
    public function equipment(): array
    {
        $time = time();
        $todayd = date('d', $time);
        $todayy = date('Y', $time);
        $todaym = date('m', $time);
        $redis = RedisTools::getInstance(config('cache.stores.redis'), 0)->getRedis();
        if (intval(date('H', time())) > 7) {
            $today_out_bag_num = $redis->get(config('ws_config.redis_key')['datacenter_statistics_out_bag_today_num']) ?: 0;
        } else {
            $num = LargeScreenCostStatistics::where(['year' => $todayy, 'month' => $todaym, 'day' => $todayd])
                ->sum('out_bag_num');
            $num = intval($num);
            $redis_num = RedisTools::getInstance(config('cache.stores.redis'), 0)->getRedis()->get(config('ws_config.redis_key')['datacenter_statistics_out_bag_today_num']) ?: 0;

            $today_out_bag_num = $num > $redis_num ? $num : $redis_num;
        }

        //设备总数
        $num = Machine::count();
        //设备离线数
        $equipment_offline_num = Machine::where('last_online_time', '<', time() - 300)->count();
//        $equipment_offline_num = rand(intval($num * 0.1), intval($num * 0.03));
        $equipment_online_num = $num - $equipment_offline_num;
        $equipment_online_per = intval(($equipment_online_num / $num) * 100);
        $data = [
            'today_out_bag_num' => $today_out_bag_num,
            'equipment_online_num' => $equipment_online_num,
            'equipment_offline_num' => $equipment_offline_num,
            'equipment_online_per' => $equipment_online_per
        ];
        //显示优化数据
        return $this->getStartData($data, 1);
    }

    /**
     * 显示优化数据
     * @param array $data
     * @param int $type
     * @return array
     */
    public function getStartData(array $data, int $type): array
    {
        //增加数据优化，开启了并且在高峰时间（9:00-19:00）段内显示优化数据last_online_time
        $out_bag_num = RedisTools::getInstance(config('cache.stores.redis'), 0)->getRedis()->get(config('ws_config.redis_key')['datacenter_statistics_out_bag_num']) ?: 8600010;//总的领袋次数
        $start = config('sys_config')['DataCenter']['data_center_start'] ?? '1';
        $gao_start_time = mktime(9, 0, 0, intval(date("m")), intval(date("d")), intval(date("Y")));
        $gao_end_time = mktime(19, 0, 0, intval(date("m")), intval(date("d")), intval(date("Y")));
        $add_equipment_num = 1800;//增加设备台数
        $avg_equipment_num = 80;//每台设备平均出袋数
        $out_bag_add_num = 9538461;//增加累计领取袋子数量
        $per = intval(($out_bag_add_num / $out_bag_num) * 100) / 100;
        //每日出袋比率增长，根据时间成长
        $today_out_bag_num = RedisTools::getInstance(config('cache.stores.redis'), 0)->getRedis()->get(config('ws_config.redis_key')['datacenter_statistics_out_bag_today_num']) ?: 20000;
        $h = 24;
        $t_h = intval(date('H'));
        $p_bag_num = intval(((($add_equipment_num * $avg_equipment_num * 1.46) / $today_out_bag_num) * ($t_h / $h)) * 100) / 100;

        $p_bag = intval(135200 / $today_out_bag_num);
        if ($start == '1') {
            if ($type == 1) {
                $num = $data['equipment_offline_num'] + $data['equipment_online_num'];
//                $p = intval((($num + $add_equipment_num) / $num) * 100) / 100;//设备增长率
                $num = $num + $add_equipment_num;
                $data['equipment_offline_num'] = rand(intval($num * 0.01), intval($num * 0.05));
                $data['equipment_online_num'] = $num - $data['equipment_offline_num'];
                $data['equipment_online_per'] = intval(($data['equipment_online_num'] / $num) * 100);
                $data['today_out_bag_num'] = intval(($data['today_out_bag_num'] * $p_bag_num) + $data['today_out_bag_num']);
                //设备在线模块
                if ($gao_start_time < time() && $gao_end_time > time() && $data['equipment_online_per'] < 95) {
                    $data['equipment_offline_num'] = rand(intval($num * 0.01), intval($num * 0.05));
                    $data['equipment_online_num'] = $num - $data['equipment_offline_num'];
                    $data['equipment_online_per'] = intval(($data['equipment_online_num'] / $num) * 100);
//                    $data['today_out_bag_num'] = intval(($data['today_out_bag_num'] * $per) + $data['today_out_bag_num']);
                }
            } elseif ($type == 5) {
                //领袋数据
//                $data['fund_pool'] = ($data['fund_pool'] * $per) + $data['fund_pool'];
                $data['out_bag_num'] = $out_bag_add_num + $data['out_bag_num'];
                $data['out_bag_user_num'] = intval(($data['out_bag_user_num'] * 3));
            } elseif ($type == 3) {
                $value_avg = 135200 - $today_out_bag_num;
                //设置数据百分比
                $value_avg_per = intval($value_avg / $today_out_bag_num);
                $h_per = [
                    0 => $value_avg * 0.013,
                    1 => $value_avg * 0.004,
                    2 => $value_avg * 0.003,
                    3 => $value_avg * 0.002,
                    4 => $value_avg * 0.001,
                    5 => $value_avg * 0.002,
                    6 => $value_avg * 0.008,
                    7 => $value_avg * 0.03,
                    8 => $value_avg * 0.035,
                    9 => $value_avg * 0.055,
                    10 => $value_avg * 0.06,
                    11 => $value_avg * 0.065,
                    12 => $value_avg * 0.052,
                    13 => $value_avg * 0.053,
                    14 => $value_avg * 0.033,
                    15 => $value_avg * 0.030,
                    16 => $value_avg * 0.045,
                    17 => $value_avg * 0.06,
                    18 => $value_avg * 0.065,
                    19 => $value_avg * 0.05,
                    20 => $value_avg * 0.05,
                    21 => $value_avg * 0.04,
                    22 => $value_avg * 0.03,
                    23 => $value_avg * 0.02,
                ];
                $h_per_yestoday = [
                    0 => $value_avg * 0.013,
                    1 => $value_avg * 0.004,
                    2 => $value_avg * 0.003,
                    3 => $value_avg * 0.002,
                    4 => $value_avg * 0.001,
                    5 => $value_avg * 0.002,
                    6 => $value_avg * 0.008,
                    7 => $value_avg * 0.03,
                    8 => $value_avg * 0.035,
                    9 => $value_avg * 0.055,
                    10 => $value_avg * 0.06,
                    11 => $value_avg * 0.055,
                    12 => $value_avg * 0.052,
                    13 => $value_avg * 0.053,
                    14 => $value_avg * 0.051,
                    15 => $value_avg * 0.055,
                    16 => $value_avg * 0.058,
                    17 => $value_avg * 0.06,
                    18 => $value_avg * 0.065,
                    19 => $value_avg * 0.05,
                    20 => $value_avg * 0.05,
                    21 => $value_avg * 0.04,
                    22 => $value_avg * 0.03,
                    23 => $value_avg * 0.02,
                ];
                //每日实时领袋数据,每天八点到晚上七点，增加数据
                if (isset($data['today']['value']) && !empty($data['today']['value'])) {
                    foreach ($data['today']['value'] as $k => $item) {
                        $data['today']['value'][$k] = intval($item + $h_per[$k]);
                    }
                }
                if (isset($data['yesterday']['value']) && !empty($data['yesterday']['value'])) {
                    foreach ($data['yesterday']['value'] as $k => $items) {
                        $data['yesterday']['value'][$k] = intval($items + $h_per_yestoday[$k]);
                    }
                }
            } elseif ($type == 4) {
                $value_avg = 135200 - $today_out_bag_num;
                $per_h = intval(date('H'));
                $per = 1 / 24;
                //城市排行版
                if (isset($data['value']) && !empty($data['value'])) {
                    $city_num = count($data['value']);
                    foreach ($data['value'] as $k => $item) {
                        $value_avg_h_num = intval(($value_avg / $city_num) * ($per * $per_h));
                        $data['value'][$k] = intval(($value_avg_h_num + $item) * (1 - (0.075 * $k)));
                    }
                }
            }
        }
        return $data;
    }

    /**
     * 获取日活排名
     * @return array[]
     */
    public function merchDayLive(): array
    {
        $redis = RedisTools::getInstance(config('cache.stores.redis'), 0)->getRedis();
        $todayDate = date('Y-m-d', time());

        $redis_shop_key = config('ws_config.redis_key')['datacenter_statistics_shop_rank_list'] . $todayDate;
        //获取分数排名(前三名)
        $list = $redis->zRevRange($redis_shop_key, 0, 2, true);
        //获取所有商家的数据
        $shop = Shop::field('name,id')->select()->toArray();
        $shopList = array_column($shop,'name','id');
        $data = [];
        if (!empty($list)) {
            $rank = 1;
            foreach ($list as $key => $item) {
                $shop_name = $shopList[$key] ?? '**商家';
                $data[] = ['name' => $shop_name, 'value' => intval($item), 'rank' => $rank++];
            }
        }
        return $data;
    }

    /**
     * 获取实时领取袋数据
     * @return array[]
     */
    public function outBagNumDay(): array
    {
        $time = time();
        $todayd = date('d', $time);
        $todayy = date('Y', $time);
        $todaym = date('m', $time);
        $today = LargeScreenCostStatistics::where(['year' => $todayy, 'month' => $todaym, 'day' => $todayd])
            ->field(['hour as name', 'out_bag_num as value'])
            ->select()
            ->toArray();
        $todayName = [];
        $todayValue = [];
        if (!empty($today)) {
            foreach ($today as $value) {
                $todayName[] = $value['name'] . ':00';
                $todayValue[] = $value['value'];
            }
        }
        $dateYesTerDayTime = strtotime(date('Y-m-d', time())) - 86400;
        $yesTerDayd = date('d', $dateYesTerDayTime);
        $yesTerDayy = date('Y', $dateYesTerDayTime);
        $yesTerDaym = date('m', $dateYesTerDayTime);
        $yesTerDay = LargeScreenCostStatistics::where(['year' => $yesTerDayy, 'month' => $yesTerDaym, 'day' => $yesTerDayd])
            ->field(['hour as name', 'out_bag_num as value'])
            ->select()
            ->toArray();
        $yesTerDayName = [];
        $yesTerDayValue = [];
        if (!empty($today)) {
            foreach ($yesTerDay as $values) {
                $yesTerDayName[] = $values['name'] . ':00';
                $yesTerDayValue[] = $values['value'];
            }
        }
        $data = [
            'today' => ['name' => $todayName, 'value' => $todayValue, 'title' => '今日'],
            'yesterday' => ['name' => $yesTerDayName, 'value' => $yesTerDayValue, 'title' => '昨日']
        ];
        return $this->getStartData($data, 3);
    }

    /**
     * 获取城市排行版
     * @return array
     */
    public function outBagTodayRank(): array
    {
        $todayDate = date('Y-m-d', time());
        $redis_city_key = config('ws_config.redis_key')['datacenter_statistics_city_list'] . $todayDate;
        $redis = RedisTools::getInstance(config('cache.stores.redis'), 0)->getRedis();
        //获取分数排名
        $list = $redis->zRevRange($redis_city_key, 0, 4, true);
        $name = [];
        $value = [];
        
        $city_ids = [];
        if (!empty($list)) {
            foreach ($list as $key => $item) {
                $city_ids[] = $key;
            }
            if(!empty($city_ids)){
                $citys = Areas::whereIn('id',$city_ids)->field('id,name')->select()->toArray();
                $citys_ids = array_column($citys,'name','id');
                foreach ($list as $key => $item) {
                    $city = $citys_ids[$key] ?? '未知';
                    $name[] = $city;
                    $city_ids[] = $key;
                    $value[] = intval($item);
                }
            }
        }
        return $this->getStartData(['title' => '今日领袋次数排行版TOP5', 'name' => $name, 'value' => $value], 4);
    }

    /**
     * 获取地图数据
     * @return array
     */
    public function outBagMapsData(): array
    {
        //获取运营城市
        $redis = RedisTools::getInstance(config('cache.stores.redis'), 0)->getRedis();
        $city = $redis->get(config('ws_config.redis_key')['datacenter_statistics_operate_city']);
        if (!$city) {
            //获取设备数据
            $out_bag_list_arr = Machine::with(['shop'])->field(['mac_id', 'shop', 'city', 'county', 'province'])->select()->toArray();
            $out_bag_list = [];
            $cityIds = [];
            if (!empty($out_bag_list_arr)) {
                foreach ($out_bag_list_arr as $k => $value) {
                    $lg = isset($value['shop']['lgt_and_lat']) && !empty($value['shop']['lgt_and_lat']) ? explode('-', $value['shop']['lgt_and_lat']) : [];
                    $out_bag_list[] = ['mac_id' => $value['mac_id'], 'longitude' => $lg[0] ?? '', 'latitude' => $lg[1] ?? ''];
                    if ($value['city'] == 429000 || $value['city'] == 469000) {
                        //湖北省级行政区
                        $cityIds[] = $value['county'];
                    } elseif ($value['city'] == 110100 || $value['city'] == 310100 || $value['city'] == 500100 || $value['city'] == 120100) {
                        //海南省级行政区
                        $cityIds[] = $value['province'];
                    } else {
                        $cityIds[] = $value['city'];
                    }
                }
            }
            if (!empty($cityIds)) $cityIds = array_filter($cityIds);
            $operating_city = Areas::where('id', 'in', $cityIds)->field(['name'])->select()->toArray();
            $city = [];
            if (!empty($operating_city)) {
                foreach ($operating_city as $value) {
                    $city[] = $value['name'];
                }
            }
            if (!empty($city)) {
                $redis->set(config('ws_config.redis_key')['datacenter_statistics_operate_city'], json_encode($city));
                $redis->expireAt(config('ws_config.redis_key')['datacenter_statistics_operate_city'], time() + 3600);
            }
        } else {
            $city = json_decode($city);
        }

        $fund_pool = Users::where('id', '=', 100301)->value('money');
        $fund_pool = intval($fund_pool * 100) / 100;
        $data = [
            'operating_city' => $city,//运营城市
            'fund_pool' => round($fund_pool, 2) ?: round(0, 2),//公益基金池
            'out_bag_num' => $redis->get(config('ws_config.redis_key')['datacenter_statistics_out_bag_num']) ?: 5000000,//累计领袋次数
            'out_bag_user_num' => $redis->pfCount(config('ws_config.redis_key')['datacenter_statistics_out_bag_user_num']) ?: 0,//累计领袋用户
        ];
        return $this->getStartData($data, 5);
    }

    /**
     * 推送一条弹幕数据
     */
    public function getMmberDataOne(array $data): bool
    {
        $machine = Machine::where(['mac_id' => $data['mac_id']])->field(['shop'])->find();
        if (!$machine) return false;
        $machine = $machine->toArray();
        $shop = Shop::where(['id' => $machine['shop']])->field(['city_id'])->find();
        if (!isset($shop['city_id'])) return false;
        $city_name = Areas::where(['id' => $shop['city_id']])->field(['name'])->find();
        if (!$city_name) return false;
        $city_name = $city_name->toArray();
        $user = Member::where(['openid' => $data['openid']])->field(['nickname'])->find();
        if (!$user) return false;
        $msg = $city_name['name'] . ' \'' . urldecode($user['nickname']) . '\' 扫码成功，无塑地球捐赠0.01元到公益基金池';
        //推送至mqtt
        $MqttClient = new EmqxHttpApi();
        $MqttClient->publish($MqttClient->emqx_datacenter_topic_js, ['type' => 6, 'data' => ['name' => $msg, 'price' => 0.01, 'city' => $city_name['name'], 'mac_id' => $data['mac_id']]]);
        //判断总领袋次数是否存在，不存在的统计数据表
        $endTime = mktime(23, 59, 59, intval(date("m")), intval(date("d")), intval(date("Y")));
        $redis = RedisTools::getInstance(config('cache.stores.redis'), 0)->getRedis();
        if (!$redis->exists(config('ws_config.redis_key')['datacenter_statistics_out_bag_num'])) {
            $num = MemberCost::count('id');
            $redis->set(config('ws_config.redis_key')['datacenter_statistics_out_bag_num'], $num);
            $redis->expireAt(config('ws_config.redis_key')['datacenter_statistics_out_bag_num'], $endTime);
        } else {
            $redis->incr(config('ws_config.redis_key')['datacenter_statistics_out_bag_num']);
        }
        //今日出袋统计
        if (!$redis->exists(config('ws_config.redis_key')['datacenter_statistics_out_bag_today_num'])) {
            $num = 0;//LargeScreenCostStatistics::where('statistical_time', '>', strtotime(date('Y-m-d', time())))->sum('out_bag_num');
            $redis->set(config('ws_config.redis_key')['datacenter_statistics_out_bag_today_num'], $num);
            $redis->expireAt(config('ws_config.redis_key')['datacenter_statistics_out_bag_today_num'], $endTime);
        } else {
            $redis->incr(config('ws_config.redis_key')['datacenter_statistics_out_bag_today_num']);
        }
        return true;
    }
}
